package com.hkbigdata.userprofile.service.impl;

import com.alibaba.fastjson.JSON;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hkbigdata.userprofile.bean.TagCondition;
import com.hkbigdata.userprofile.bean.TagInfo;
import com.hkbigdata.userprofile.bean.UserGroup;
import com.hkbigdata.userprofile.constants.ConstCodes;
import com.hkbigdata.userprofile.mapper.UserGroupMapper;
import com.hkbigdata.userprofile.service.TagInfoService;
import com.hkbigdata.userprofile.service.UserGroupService;
import com.hkbigdata.userprofile.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;

import javax.print.DocFlavor;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 服务实现类
 * </p>
 */
@Service
@Slf4j
@DS("mysql")
public class UserGroupServiceImpl extends ServiceImpl<UserGroupMapper, UserGroup> implements UserGroupService {
    @Autowired
    TagInfoService tagInfoService;
    @Autowired
    UserGroupMapper userGroupMapper;

    @Override
    public void genUserGroup(UserGroup userGroup) {
        //1.将基本数据写到MySQL
        //补充字段数据
        //1.1 创建时间
        userGroup.setCreateTime(new Date());
        //1.2 查询条件
        List<TagCondition> tagConditions = userGroup.getTagConditions();
        userGroup.setConditionJsonStr(JSON.toJSONString(tagConditions));
        //1.3 分群说明
        userGroup.setConditionComment(userGroup.conditionJsonToComment());

        //基本信息写入到mysql
        saveOrUpdate(userGroup);


        /**
         * select
         *   bitmapToArray(  bitmapAnd(
         * 	 bitmapAnd(
         * 	   (select  groupBitmapMergeState(us)  from user_tag_value_string where  tag_code ='tg_person_base_gender' and tag_value='女性’ and dt=‘2021-05-16’)
         * 	    ,
         * 	   (select groupBitmapMergeState( us)  from user_tag_value_string where  tag_code ='tg_person_base_agegroup' and tag_value in ('70后','80后’) and dt=‘2021-05-16’)
         * 	 ),
         * 	 (select  groupBitmapMergeState(us)  from user_tag_value_long where  tag_code ='tg_behavior_order_last30_ct' and tag_value >= 1 and dt=‘2021-05-16’)
         *  )
         * )
         * ;
         */
        /**
         *    1    表名           要查询mysql 中tag_info 中的tag_value_type
         *    2    tag_code  ->  参数
         *    3   tag_value     ->   参数
         *         加不加单引     ->要查询mysql 中tag_info 中的tag_value_type
         *         一个还是多个  -> 根据tagvalues 数组长度
         *   4   符号       ->  要根据operator  进行转义 =   >=    in  not in
         *   5   业务日期  -> 参数
         */
        //2.查询分群数据，将其写到clickhouse 分群包里面
        String genBitSql = genBitSql(userGroup.getTagConditions(), userGroup.getBusiDate());

        //查询sql
        insersql(genBitSql, userGroup.getId().toString());

        //3.将clickhouse分群数据写入到redis
        //根据分组的user_group_id查询ck ,查询ck bitmap数据转换为array
        List<String> stringList = baseMapper.getSelectUsergroupById(userGroup.getId().toString());
        //list转换为数组
        String[] array = stringList.toArray(new String[]{});
        //拼接key
        String key = "user_group_" + userGroup.getId();

        //获取连接
        Jedis jedis = RedisUtil.getJedisFromPool();
        jedis.del(key);
        jedis.sadd(key, array);
        jedis.close();

        //更新时间和更新人数
        String selectsql = "select bitmapCardinality(" + genBitSql + ")";

        Long byIdCount = baseMapper.getSelectUsergroupByIdCount(selectsql);
        userGroup.setUserGroupNum(byIdCount);
        userGroup.setUpdateTime(new Date());
        saveOrUpdate(userGroup);


    }

    @Override
    public Long userGroupEvaluate(UserGroup userGroup) {
        //根据组合条件获得查询sql
        String bitSql = genBitSql(userGroup.getTagConditions(), userGroup.getBusiDate());
        //count(distinct id)
        String selectsql = "select bitmapCardinality(" + bitSql + ")";

        Long byIdCount = baseMapper.getSelectUsergroupByIdCount(selectsql);

        return byIdCount;
    }

    @Override
    public void refreshUserGroup(String userGroupId, String busiDate) {
        //删除对应的分群数据
        baseMapper.DeleteUsergroupById(userGroupId);

        UserGroup userGroup = baseMapper.selectById(userGroupId);
        String conditionJsonStr = userGroup.getConditionJsonStr();
        List<TagCondition> tagConditions = JSON.parseArray(conditionJsonStr, TagCondition.class);

        userGroup.setTagConditions(tagConditions);
        userGroup.setBusiDate(busiDate);

        //更新数据
        genUserGroup(userGroup);

    }

    public void insersql(String genBitSql, String usergroupid) {

        String insertsql = "";

        insertsql = "insert into user_group " + "select " + usergroupid + "," + genBitSql;
        System.out.println("执行成功" + insertsql);
        userGroupMapper.insertsql(insertsql);


    }

    // 拆分成简单sql
//    bitmapAnd(
//       bitmapAnd(
//         (sql1),
//         (sql2)
//         ),
//        (sql3)
//     )
    public String genBitSql(List<TagCondition> tagConditions, String busiDate) {
        Map<String, TagInfo> tagInfoMapWithCode = tagInfoService.getTagInfoMapWithCode();

        String bitsql = null;
        for (TagCondition tagCondition : tagConditions) {
            //表示只有一个条件
            if (bitsql == null) {
                bitsql = "(" + conditinSql(tagCondition, tagInfoMapWithCode, busiDate) + ")";
            } else {
                bitsql = " bitmapAnd (" + bitsql + ",(" + conditinSql(tagCondition, tagInfoMapWithCode, busiDate) + ")" + ")";
            }
        }

        return bitsql;

    }

    public String conditinSql(TagCondition tagCondition, Map<String, TagInfo> tagInfoMapWithCode, String busiDate) {

        String condtionsql = "";
        String tagCode = tagCondition.getTagCode();
        TagInfo tagInfo = tagInfoMapWithCode.get(tagCode);
        //1,2,3,4
        String tagValueType = tagInfo.getTagValueType();
        String tablename = gettablename(tagValueType);

        String operator = tagCondition.getOperator();
        List<String> tagValues = tagCondition.getTagValues();


        condtionsql = "select  groupBitmapMergeState(us)  from " + tablename + " where tag_code='" + tagCode.toLowerCase() + "'" +
                " and " + getTagValues(tagValues, tagValueType, operator) + " and dt='" + busiDate + "'";

        return condtionsql;


    }

    public String getoperator(String operator) {
        switch (operator) {
            case "eq":
                return "=";
            case "lte":
                return "<=";
            case "gte":
                return ">=";
            case "lt":
                return "<";
            case "gt":
                return ">";
            case "neq":
                return "<>";
            case "in":
                return "in";
            case "nin":
                return "not in";
        }
        throw new RuntimeException("操作符不正确");
    }

    public String getTagValues(List<String> tagValues, String tagValueType, String operator) {
        String tagValue = "";
        if (tagValueType.equals(ConstCodes.TAG_VALUE_TYPE_STRING) || tagValueType.equals(ConstCodes.TAG_VALUE_TYPE_DATE)) {
            //'zhangsan','lisi','wangwu'
            tagValue = "'" + StringUtils.join(tagValues, "','") + "'";
        } else {
            tagValue = StringUtils.join(tagValues, ",");
        }

        if (tagValues.size() > 1) {
            //where tag_value in ( 'tag_value')
            tagValue = "(" + tagValue + ")";
        }


        tagValue = " tag_value " + getoperator(operator) + " " + tagValue;
        return tagValue;
    }

    public String gettablename(String tagValueType) {
        String tablename = "user_tag_value_";
        if (tagValueType.equals(ConstCodes.TAG_VALUE_TYPE_STRING)) {
            return tablename + "string";
        } else if (tagValueType.equals(ConstCodes.TAG_VALUE_TYPE_LONG)) {
            return tablename + "long";
        } else if (tagValueType.equals(ConstCodes.TAG_VALUE_TYPE_DATE)) {
            return tablename + "date";
        } else if (tagValueType.equals(ConstCodes.TAG_VALUE_TYPE_DECIMAL)) {
            return tablename + "decimal";
        } else {
            throw new RuntimeException("类型不匹配");
        }

    }


}
